package com.gitee.wsl.coroutines.api

import com.gitee.wsl.coroutines.exception.UncaughtExceptionHandler

/**
 * Represents a callback that will be invoked when a task completes.
 *
 *
 * A task can complete either successfully with a value, or with an exception,
 * or it can be cancelled.
 *
 *
 * MUST BE idempotent AND thread-safe.
 *
 * @param <T> is the type of the value that the task will complete with
</T> */
fun interface CompletionCallback<T> {

    fun onOutcome(outcome: Outcome<T>)

    /**
     * Must be called when the task completes successfully.
     *
     * @param value is the successful result of the task, to be signaled
     */
    fun onSuccess(value: T) {
        onOutcome(Outcome.success(value))
    }

    /**
     * Must be called when the task completes with an exception.
     *
     * @param e is the exception that the task failed with
     */
    fun onFailure(e: Throwable) {
        onOutcome(Outcome.failure(e))
    }

    /**
     * Must be called when the task is cancelled.
     */
    fun onCancellation() {
        onOutcome(Outcome.cancellation())
    }

    companion object {
        /**
         * @return a `CompletionListener` that does nothing.
         */
        fun <T> empty(): CompletionCallback<T> {
            return CompletionCallback<T> { outcome: Outcome<T> ->
                if (outcome is Outcome.Failure<T>) {
                    UncaughtExceptionHandler.rethrowIfFatal(outcome.exception)
                }
            }
        }
    }
}